﻿using System.Collections;
using System.Collections.Generic;
using LuaInterface;
using UnityEngine;

namespace Framework.UGUI
{
    public static class RectTrHelper
    {
        private static Vector2 _tempVector2;
        private static Vector3 _tempVector3;

        public static void SetHeight(this RectTransform rectTr, float height)
        {
            rectTr.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, height);
        }

        public static float GetHeight(this RectTransform rectTr)
        {
            return rectTr.rect.height;
        }

        public static void SetWidth(this RectTransform rectTr, float width)
        {
            rectTr.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, width);
        }

        public static float GetWidth(this RectTransform rectTr)
        {
            return rectTr.rect.width;
        }

        public static void SetSize(this RectTransform rectTr, float width, float height)
        {
            rectTr.SetWidth(width);
            rectTr.SetHeight(height);
        }

        public static void SetSizeByAxis(this RectTransform rectTransform, int axis, float sizeValue)
        {
	        rectTransform.SetSizeWithCurrentAnchors((RectTransform.Axis)axis, sizeValue);
        }

        public static float GetSize(this RectTransform rectTr, int axis)
        {
            if (0 == axis)
            {
                return rectTr.rect.width;
            }
            if (1 == axis)
            {
                return rectTr.rect.height;
            }
            return 0;
        }

        public static float GetAnchorX(this RectTransform rectTr)
        {
			return rectTr.anchoredPosition.x;
        }

        public static float GetAnchorY(this RectTransform rectTr)
        {
			return rectTr.anchoredPosition.y;
        }

        public static void GetAnchor(this RectTransform rectTr, out float x, out float y)
        {
            Vector2 anchor = rectTr.anchoredPosition;
            x = anchor.x;
            y = anchor.y;
        }

        public static void SetAnchorX(this RectTransform rectTr, float posX)
        {
            rectTr.anchoredPosition = new Vector2(posX, rectTr.anchoredPosition.y);
        }

        public static void SetAnchorY(this RectTransform rectTr, float posY)
        {
            rectTr.anchoredPosition = new Vector2(rectTr.anchoredPosition.x, posY);
        }

        public static void SetAnchor(this RectTransform rectTr, float posX, float posY)
        {
            rectTr.anchoredPosition = new Vector2(posX, posY);
        }

        public static Vector2 ScreenPosToAnchorPos(Vector2 screenPos, RectTransform rect, Camera uiCamera)
        {
            Vector2 rectPos;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(rect, screenPos, uiCamera, out rectPos);
            return rectPos;
        }

        public static void ScreenPosToAnchorPos2(Vector2 screenPos, RectTransform rect, Camera uiCamera, out float rectPosX, out float rectPosY)
        {
	        Vector2 rectPos;
	        RectTransformUtility.ScreenPointToLocalPointInRectangle(rect, screenPos, uiCamera, out rectPos);
	        rectPosX = rectPos.x;
	        rectPosY = rectPos.y;
        }

        public static void ScreenPosXYToAnchorPosXY(float screenPosX, float screenPosY, RectTransform rect, Camera uiCamera, out float rectPosX, out float rectPosY)
        {
            Vector2 rectPos;
            _tempVector2.Set(screenPosX, screenPosY);
            RectTransformUtility.ScreenPointToLocalPointInRectangle(rect, _tempVector2, uiCamera, out rectPos);
            rectPosX = rectPos.x;
            rectPosY = rectPos.y;
        }

        public static Vector2 WorldPosToAnchorPos(Vector3 worldPos, RectTransform planeRectTr, Camera uiCamera, Camera camera3d)
        {
            Vector3 screenPoint = camera3d.WorldToScreenPoint(worldPos);
            Vector2 rectPos;
            if (RectTransformUtility.ScreenPointToLocalPointInRectangle(planeRectTr, screenPoint, uiCamera, out rectPos))
            {
                return rectPos;
            }
            return rectPos;
        }

        /// <summary>
        /// 世界坐标转UGUI坐标，会有较高的lua内存消耗，建议使用 WorldPosToAnchorPosXYZ
        /// </summary>
        public static void WorldPosToAnchorPos2(Vector3 worldPos, RectTransform planeRectTr, Camera uiCamera, Camera camera3d, out float rectPosX, out float rectPosY)
        {
	        Vector3 screenPoint = camera3d.WorldToScreenPoint(worldPos);
	        Vector2 rectPos;
	        RectTransformUtility.ScreenPointToLocalPointInRectangle(planeRectTr, screenPoint, uiCamera, out rectPos);
	        rectPosX = rectPos.x;
	        rectPosY = rectPos.y;
        }

        /// <summary>
        /// 世界坐标转UGUI坐标
        /// </summary>
        public static void WorldPosToAnchorPosXYZ(float worldPosX, float worldPosY, float worldPosZ, RectTransform planeRectTr, Camera uiCamera, Camera camera3d, out float rectPosX, out float rectPosY)
        {
            _tempVector3.Set(worldPosX, worldPosY, worldPosZ);
            Vector3 screenPoint = camera3d.WorldToScreenPoint(_tempVector3);
            Vector2 rectPos;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(planeRectTr, screenPoint, uiCamera, out rectPos);
            rectPosX = rectPos.x;
            rectPosY = rectPos.y;
        }

        /// <summary>
        /// 屏幕坐标转换为3D空间的世界坐标，必须有参照物体才知道转换到那个z轴平面的世界坐标。
        /// refGOWorldPos 世界的一个参考物体的世界坐标，需要转换到与此参照物体同一个z轴坐标的
        /// </summary>
        public static Vector3 ScreenPosToWorldPos(Vector2 screenPos, Camera worldCamera, Vector3 refGOWorldPos)
        {
            //dir为由摄像机指向点的向量
            Vector3 dir = refGOWorldPos - worldCamera.transform.position;
            //指向摄像机正前方的单位向量
            Vector3 forward = worldCamera.transform.forward;
            //Vector3.Dot(dir, forward)为dir与forward的点乘，几何意义为dir在forward上的投影
            Vector3 screenPosForCurz = Vector3.right * screenPos.x + Vector3.up * screenPos.y + Vector3.forward * Vector3.Dot(dir, forward);
            return worldCamera.ScreenToWorldPoint(screenPosForCurz);
        }

        public static void ScreenPosToWorldPos3(Vector2 screenPos, Camera worldCamera, Vector3 refGOWorldPos, out float posX, out float posY, out float posZ)
        {
            //dir为由摄像机指向点的向量
            Vector3 dir = refGOWorldPos - worldCamera.transform.position;
            //指向摄像机正前方的单位向量
            Vector3 forward = worldCamera.transform.forward;
            //Vector3.Dot(dir, forward)为dir与forward的点乘，几何意义为dir在forward上的投影
            Vector3 screenPosForCurz = Vector3.right * screenPos.x + Vector3.up * screenPos.y + Vector3.forward * Vector3.Dot(dir, forward);
            Vector3 result = worldCamera.ScreenToWorldPoint(screenPosForCurz);
            posX = result.x;
            posY = result.y;
            posZ = result.z;
        }

        public static Vector2 UIPosToScreenPos(RectTransform rect, Canvas canvas)
        {
            if (canvas.renderMode != RenderMode.ScreenSpaceOverlay)
                return canvas.worldCamera.WorldToScreenPoint(rect.position);
            return rect.position;
        }

        public static void UIPosToScreenPos2(RectTransform rect, Canvas canvas, out float screenPosX, out float screenPosY)
        {
            var result = rect.position;
            if (canvas.renderMode != RenderMode.ScreenSpaceOverlay)
                result = canvas.worldCamera.WorldToScreenPoint(rect.position);
            screenPosX = result.x;
            screenPosY = result.y;
        }
        public static bool ScreenPosInRect(RectTransform rectTr, Camera uiCamera, float x, float y, out bool inRect)
        {
            _tempVector2.Set(x, y);
            inRect = RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTr, _tempVector2, uiCamera, out _tempVector2);
            if (inRect)
            {
                inRect = rectTr.rect.Contains(_tempVector2);
            }
            return inRect;
        }
        public static void WorldPosToScreenPoint(Camera camera, float worldPosX, float worldPosY, float worldPosZ, 
            out float screenPosX, out float screenPosY, out float screenPosZ)
        {
            _tempVector3.Set(worldPosX, worldPosY, worldPosZ);
            _tempVector3 = camera.WorldToScreenPoint(_tempVector3);
            screenPosX = _tempVector3.x;
            screenPosY = _tempVector3.y;
            screenPosZ = _tempVector3.z;
        }
    }
}
